const Account = require('../../domain/auth/account')
const {
  AccountNotFoundError,
  AccountDisabledError,
  PasswordNotMatchError,
} = require('../../domain/auth/error')
const Token = require('../../domain/auth/token')
const Usecase = require('../../shared/usecase/Usecase')

class Login extends Usecase {
  constructor({ userRepo, database, config }) {
    super(['Logined'])
    this.userRepo = userRepo
    this.sequelize = database.sequelize
    this.config = config
  }

  async execute(data) {
    const account = Account.create(data)
    // 验证阶段
    await account.validate()
    let user = await this.userRepo.findByAccount(data.account)
    if (!user) throw new AccountNotFoundError(data.account)
    if (!(await user.comparePassword(account.password)))
      throw new PasswordNotMatchError(data.account)
    if (user.isDisabled()) throw new AccountDisabledError()

    const transaction = await this.sequelize.transaction()
    try {
      // 更新登录状态
      user.lastLoginIp = data.ip
      user.lastLoginAt = new Date()
      await this.userRepo.update(user, { transaction }, false)
      // 生成token
      const token = Token.createFromUser(user, this.config.get('jwt'))
      token.sign()
      await transaction.commit()
      return token
    } catch (error) {
      await transaction.rollback()
      throw error
    }
  }
}

module.exports = Login
